////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  GameRuleProxy.m
//  PokerHandUp
//
//  Created by psvn047 on 6/20/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#import "GameRuleProxy.h"
#import "CheckCardUtils.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@implementation GameRuleProxy
@synthesize gameRuleProxyCallback = _gameRuleProxyCallback;
@synthesize myPlayer = _myPlayer;
@synthesize rivalPlayer = _rivalPlayer;
NSMutableArray * cardArr;

long SB = 10; // $10
long BB = 20;
long tMoney = 0;
long rMoney = 0;
long mMoney = 0;
int stepRound = stepTurn2Card;
int gStatus = rCheckControl;
bool isAssignDealer;
NSString * dealerName;
NSMutableArray *myListCards;
NSMutableArray *rivalListCards;
NSMutableArray *turnListCards;
bool mShowHand;
bool rShowHand;

bool mAllowCheck;
bool rAllowCheck;
bool mCheck;
bool rCheck;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-(id) init
{
    self = [super init];
    
    myPlayer = [[PlayerInfo alloc] init];
    myPlayer.ID = @"MyPlayer";
    myPlayer.Username = @"MyPlayer";
    myPlayer.Avatar = [[AppDelegate sharedController].avatarCollection randomAvatar].image;
    myPlayer.Level = 10;
    myPlayer.Money = 10000;
    
    return self;
}

-(void) startGame
{
    if(rivalPlayer)
    {
        [rivalPlayer release];
        rivalPlayer = nil;
    }
    
    rivalPlayer = [[PlayerInfo alloc] init];
    rivalPlayer.ID = @"RivalPlayer";
    rivalPlayer.Username = @"RivalPlayer";
    rivalPlayer.Avatar = [[AppDelegate sharedController].avatarCollection randomAvatar].image;
    rivalPlayer.Level = 10;
    rivalPlayer.Money = 10000;
    if(myPlayer.Money <=BB) // add Money for myPlayer
    {
        myPlayer.Money += 500;
    }
   
    // Create players
    NSMutableDictionary * startGameInfo = [NSMutableDictionary dictionary];
    [startGameInfo setObject:rivalPlayer forKey:@"rivalPlayer"];
    [startGameInfo setObject:myPlayer forKey:@"myPlayer"];
    [self.gameRuleProxyCallback startGameCallback:startGameInfo];
    
}
-(void) startRound
{
    NSLog(@"=========== GameRuleProxy - StartRound ===========");
    NSLog(@"** MyTotalMoney is %ld --- RivalTotalMoney %ld -- Total Money is %ld", myPlayer.Money, rivalPlayer.Money, myPlayer.Money + rivalPlayer.Money);
    //////////////////////////////////////////////////////////////////////
    //Reset round
    if (myListCards) {
        [myListCards release];
    }
    if (rivalListCards) {
        [rivalListCards release];
    }
    if (turnListCards) {
        [turnListCards release];
    }
    
    myListCards = [[NSMutableArray alloc] init];
    rivalListCards = [[NSMutableArray alloc] init];
    turnListCards = [[NSMutableArray alloc] init];
    
    mShowHand = false;
    rShowHand = false;
    rCheck = false;
    mCheck = false;
    rAllowCheck = false;
    mAllowCheck = false;
    cardArr = (NSMutableArray*) [[[[AppDelegate sharedController] deck] cards] mutableCopy];
    stepRound = stepTurn2Card;
    ////////////////////////////////////////////////////////////////////////
    // create object callback
    NSMutableDictionary * gameInfo = [NSMutableDictionary dictionary];
    [gameInfo setObject:[NSString stringWithFormat:@"%d",SB] forKey:@"SB"];
    BB = SB*2;
    tMoney = SB * 3;
    // assign dealer for players
     if(random() % 2)
     {
         [gameInfo setObject:myPlayer.Username forKey:@"dealer"];
         [gameInfo setObject:myPlayer.Username forKey:@"smallblind"];
         [gameInfo setObject:rivalPlayer.Username forKey:@"bigblind"];
         [gameInfo setObject:myPlayer.Username forKey:@"playercontrol"];
         gStatus = rMyControl;
         rMoney = BB;
         mMoney = SB;
         dealerName = myPlayer.Username;
     }
     else {
         [gameInfo setObject:rivalPlayer.Username forKey:@"dealer"];
         [gameInfo setObject:rivalPlayer.Username forKey:@"smallblind"];
         [gameInfo setObject:myPlayer.Username forKey:@"bigblind"];
         [gameInfo setObject:rivalPlayer.Username forKey:@"playercontrol"];
         gStatus = rRivalControl;
         rMoney = SB;
         mMoney = BB;
         dealerName = rivalPlayer.Username;
     }
    
     // isAssignDealer = true because player's control was assigned
     isAssignDealer = true;
     // create cards for myPlayer and rivalPlayer
     NSArray* nextCards = [self randRankCard:2];
     [myListCards addObjectsFromArray:nextCards];
     nextCards = [self randRankCard:2];
     [rivalListCards addObjectsFromArray:nextCards];
     [gameInfo setObject:rivalListCards forKey:@"rivalcards"];
     [gameInfo setObject:myListCards forKey:@"mycards"];
     // call startRoundCallback
     [self.gameRuleProxyCallback startRoundCallback:gameInfo];
}
-(int) AIControl:(bool) isCheck
{
    long temp = abs(arc4random()) % 100 + 1;
    if(isCheck) // if AI is allowed selecting Check
    {
        if(temp <= 30) //30% (1-30)
        {
            return cCheck;
        }
        else if (temp <= 40) //10% (31-40)
        {
            return cRaise;
        }
        else if (temp <= 95) //45% (41-95) 
        {
            return cCall;
        }
        else if (temp <= 100) // 5% (96-100)
        {
            return cFold;
        }
    }
    else 
    {
        if (temp <= 10) //10% (0-10)
        {
            return cRaise;
        }
        else if (temp <= 95) //85% (11-95) 
        {
            return cCall;
        }
        else if (temp <= 100) // 5% (96-100)
        {
            return cFold;
        }
    }
    return cCall; //default
}
-(void) requestStatus
{
    NSMutableDictionary * gameInfo = [NSMutableDictionary dictionary];
    switch (gStatus) 
    {
        // status is CheckControl
        case rCheckControl: 
            if((mShowHand && rShowHand) || (mCheck && rCheck))
            {
                gStatus = rNextStep;
            }
            else if(mShowHand)
            {
                if(mMoney <= rMoney)
                {
                    rShowHand = true;
                    gStatus = rNextStep;
                }
                else
                {
                    gStatus = rRivalControl;
                }
            }
            else if(rShowHand)
            {
                if(rMoney <= mMoney)
                {
                    mShowHand = true;
                    gStatus = rNextStep;
                }
                else 
                {
                    gStatus = rMyControl;
                }
            }
            else if(isAssignDealer)
            {
                if(mCheck)
                {
                    rAllowCheck = true;
                    gStatus = rRivalControl;
                }
                else if(rCheck)
                {
                    mAllowCheck = true;
                    gStatus = rMyControl;
                }
                else if(mMoney == rMoney)
                {
                    gStatus = rNextStep;
                }
                else 
                {
                    if(mMoney < rMoney)
                    {
                        gStatus = rMyControl;
                    }
                    else 
                    {
                        gStatus = rRivalControl;
                    }
                }
             }
             else 
             {
                if(dealerName == myPlayer.Username)
                {
                    gStatus = rRivalControl;
                    rAllowCheck = true;
                }
                else 
                {
                    gStatus = rMyControl;
                    mAllowCheck = true;
                }
             }
            
            [gameInfo setObject:[NSString stringWithFormat:@"%d",rCheckControl] forKey:@"status"];
            [self.gameRuleProxyCallback requestStatusCallback:gameInfo];

            break;
        // status is RivalControl
        case rRivalControl:
            if(rShowHand)
            {
                // check rShowHand
                [gameInfo setObject:@"TRUE" forKey:@"rShowHand"];
            }
            else 
            {
                [gameInfo setObject:@"FALSE" forKey:@"rShowHand"];
                [self.gameRuleProxyCallback showTimerCallback];
                //dealerName = rivalPlayer.Username;
                
                //int AICall = [self AIControl:false];
                int AICall = [self AIControl:rAllowCheck];
                switch (AICall) 
                {
                    case cCheck:
                        [gameInfo setObject:[NSString stringWithFormat:@"%d",0] forKey:@"money"];
                        [gameInfo setObject:[NSString stringWithFormat:@"%d",cCheck] forKey:@"control"];
                        rCheck = true;
                        break;
                    case cRaise:
                        rCheck = false;
                        rAllowCheck = false;
                        mCheck = false;
                        mAllowCheck = false;
                        if(mShowHand)
                        {
                            rShowHand = true;
                        }
                        if(rivalPlayer.Money + rMoney < mMoney)
                        {
                            rMoney += rivalPlayer.Money;
                            tMoney += rivalPlayer.Money;
                            [gameInfo setObject:[NSString stringWithFormat:@"%d",rivalPlayer.Money] forKey:@"money"];
                            rShowHand = true;
                            // money do not enough to raise
                            [gameInfo setObject:[NSString stringWithFormat:@"%d",cRaise] forKey:@"control"];
                        }
                        else if(rMoney == mMoney)
                        {
                            long tmp;
                            if(BB >rivalPlayer.Money)
                            {
                                tmp = rivalPlayer.Money;
                                rMoney += rivalPlayer.Money;
                                tMoney += rivalPlayer.Money;
                                rShowHand = true;
                            }
                            else 
                            {
                                tmp = BB;
                                rMoney += BB;
                                tMoney += BB;
                            }
                            
                            [gameInfo setObject:[NSString stringWithFormat:@"%d",tmp] forKey:@"money"];
                            [gameInfo setObject:[NSString stringWithFormat:@"%d",cRaise] forKey:@"control"];
                        }
                        else 
                        {
                            long tmp = abs(rMoney - mMoney);
                            if(tmp > rivalPlayer.Money)
                            {
                                tmp = rivalPlayer.Money;
                                rShowHand = true;
                            }
                            rMoney += tmp;
                            tMoney += tmp;
                            [gameInfo setObject:[NSString stringWithFormat:@"%d",tmp] forKey:@"money"];
                            [gameInfo setObject:[NSString stringWithFormat:@"%d",cRaise] forKey:@"control"];
                        }

                        break;
                    case cCall:
                        rCheck = false;
                        rAllowCheck = false;
                        mCheck = false;
                        mAllowCheck = false;
                        if(mShowHand)
                        {
                            rShowHand = true;
                        }
                        if(rivalPlayer.Money + rMoney < mMoney)
                        {
                            rMoney += rivalPlayer.Money;
                            tMoney += rivalPlayer.Money;
                            [gameInfo setObject:[NSString stringWithFormat:@"%d",rivalPlayer.Money] forKey:@"money"];
                            rShowHand = true;
                            [gameInfo setObject:[NSString stringWithFormat:@"%d",cCall] forKey:@"control"];
                        }
                        else if(rMoney == mMoney)
                        {
                            long tmp;
                            if(BB >rivalPlayer.Money)
                            {
                                tmp = rivalPlayer.Money;
                                rMoney += rivalPlayer.Money;
                                tMoney += rivalPlayer.Money;
                                rShowHand = true;
                            }
                            else 
                            {
                                tmp = BB;
                                rMoney += BB;
                                tMoney += BB;
                            }
                            
                            [gameInfo setObject:[NSString stringWithFormat:@"%d",tmp] forKey:@"money"];
                            [gameInfo setObject:[NSString stringWithFormat:@"%d",cCall] forKey:@"control"];
                        }
                        else 
                        {
                            long tmp = abs(rMoney - mMoney);
                            if(tmp > rivalPlayer.Money)
                            {
                                tmp = rivalPlayer.Money;
                                rShowHand = true;
                            }
                            rMoney += tmp;
                            tMoney += tmp;
                            [gameInfo setObject:[NSString stringWithFormat:@"%d",tmp] forKey:@"money"];
                            [gameInfo setObject:[NSString stringWithFormat:@"%d",cCall] forKey:@"control"];
                        }
                        break;  
                    case cFold:
                    {
                        [gameInfo setObject:[NSString stringWithFormat:@"%d",cFold] forKey:@"control"];
                        if(mMoney >= rMoney)
                        {
                            [gameInfo setObject:[NSString stringWithFormat:@"%d",tMoney] forKey:@"money"];
                            [gameInfo setObject:[NSString stringWithFormat:@"%d",0] forKey:@"returnmoney"];
                        }
                        else if (mMoney < rMoney) 
                        {
                           long returnMoney = abs(mMoney - rMoney);
                            [gameInfo setObject:[NSString stringWithFormat:@"%d",tMoney - returnMoney] forKey:@"money"];
                            [gameInfo setObject:[NSString stringWithFormat:@"%d",returnMoney] forKey:@"returnmoney"];
                            
                        }
                    }
                    break;
                    default:
                        break;
                }
            }
            // 
            gStatus = rCheckControl;
            [gameInfo setObject:[NSString stringWithFormat:@"%d",rRivalControl] forKey:@"status"];
            isAssignDealer = true;
            [self performSelector:@selector(AIControlCallback:) withObject:gameInfo afterDelay:3];
        break;
        // status is MyControl
        case rMyControl:
            [gameInfo setObject:[NSString stringWithFormat:@"%d",rMyControl] forKey:@"status"];
            if (mAllowCheck)
            {
                [gameInfo setObject:@"TRUE" forKey:@"mAllowCheck"];
            }
            else 
            {
                [gameInfo setObject:@"FALSE" forKey:@"mAllowCheck"];
            }
            isAssignDealer = true;
            //dealerName = myPlayer.Username;
            [self.gameRuleProxyCallback requestStatusCallback:gameInfo];

            break;
        // status is NextStep
        case rNextStep:
            NSLog(@"** mMoney is %ld -- rMoney is %ld -- tMoney is %ld", mMoney, rMoney, tMoney);
            stepRound = [self nextStep:stepRound];
            gStatus = rCheckControl;
            isAssignDealer = false;
            rCheck = false;
            mCheck = false;
            rAllowCheck = false;
            mAllowCheck = false;
            NSArray *nextCards;
            [gameInfo setObject:[NSString stringWithFormat:@"%d",rNextStep] forKey:@"status"];
            [gameInfo setObject:[NSString stringWithFormat:@"%d",stepRound] forKey:@"step"];
            if(stepRound == stepTurn3Card)
            {
                nextCards = [self randRankCard:3];
                [turnListCards addObjectsFromArray:nextCards];
                [gameInfo setObject:nextCards forKey:@"turncards"];
            }
            else if(stepRound == stepTurnCard)
            {
                nextCards =[self randRankCard:1];
                [turnListCards addObjectsFromArray:nextCards];
                [gameInfo setObject:nextCards forKey:@"turncards"];
            }
            else if(stepRound == stepRiverCard)
            {
                nextCards =[self randRankCard:1];
                [turnListCards addObjectsFromArray:nextCards];
                [gameInfo setObject:nextCards forKey:@"turncards"];
            } 
            else if(stepRound == stepEndCard)
            {
                isAssignDealer = true;
            } 
            [self.gameRuleProxyCallback requestStatusCallback:gameInfo];
            break;
        default:
            break;
    }
}
-(void) AIControlCallback:(NSMutableDictionary*) data
{
    [self.gameRuleProxyCallback requestStatusCallback:data];
}
-(StepRound) nextStep:(StepRound) currentStep
{
    switch (currentStep) 
    {
        case stepTurn2Card:
              return  stepTurn3Card;
            break;
        case stepTurn3Card:
            return  stepTurnCard;
            break;
        case stepTurnCard:
            return  stepRiverCard;
            break;
        case stepRiverCard:
            return  stepEndCard;
            break;
        case stepEndCard:
            return  stepTurn2Card;
            break;
        default:
            break;
    }
}
-(void) doAction:(int) action money:(long) money
{
    long returnMoney;
    NSMutableDictionary * gameInfo = [NSMutableDictionary dictionary];
    [gameInfo setObject:[NSString stringWithFormat:@"%d",action] forKey:@"action"];
    switch (action) {
        case cCheck:
            mCheck = true;
            gStatus = rCheckControl;
            [self.gameRuleProxyCallback doActionCallback:gameInfo];
            break;
        case cRaise:
            rCheck = false;
            rAllowCheck = false;
            mCheck = false;
            mAllowCheck = false;
            if(rShowHand)
            {
                mShowHand = true;
            }
            if(money > 0)
            {
                mMoney += money;
                tMoney += money;
                if(money == myPlayer.Money)
                {
                    mShowHand = true;
                }
                [gameInfo setObject:[NSString stringWithFormat:@"%d",money] forKey:@"money"];
            }
            else 
            {
                [gameInfo setObject:[NSString stringWithFormat:@"%d",0] forKey:@"money"];
            }
            
            gStatus = rCheckControl;
            [self.gameRuleProxyCallback doActionCallback:gameInfo];
        break;
        case cCall:
            rCheck = false;
            rAllowCheck = false;
            mCheck = false;
            mAllowCheck = false;
            if(rShowHand)
            {
                mShowHand = true;
            }
            if(rMoney == mMoney)
            {
                long tmp;
                if(BB >= myPlayer.Money)
                {
                    tmp = myPlayer.Money;
                    mMoney += myPlayer.Money;
                    tMoney += myPlayer.Money;
                    mShowHand = true;
                }
                else 
                {
                    tmp = BB;
                    mMoney += BB;
                    tMoney += BB;
                }
                [gameInfo setObject:[NSString stringWithFormat:@"%d",tmp] forKey:@"money"];
            }
            else {
                int tmp = abs(rMoney - mMoney);
                if(tmp > myPlayer.Money)
                {
                    tmp = myPlayer.Money;
                    mShowHand = true;
                }
                mMoney += tmp;
                tMoney += tmp;
                [gameInfo setObject:[NSString stringWithFormat:@"%d",tmp] forKey:@"money"];
            }
            gStatus = rCheckControl;
            [self.gameRuleProxyCallback doActionCallback:gameInfo];
        break;
        case cFold:
            if(mMoney <= rMoney)
            {
                [gameInfo setObject:[NSString stringWithFormat:@"%d",tMoney] forKey:@"money"];
                [gameInfo setObject:[NSString stringWithFormat:@"%d",0] forKey:@"returnmoney"];
            }
            else if (mMoney > rMoney) 
            {
                returnMoney = abs(mMoney - rMoney);
                [gameInfo setObject:[NSString stringWithFormat:@"%d",tMoney - returnMoney] forKey:@"money"];
                [gameInfo setObject:[NSString stringWithFormat:@"%d",returnMoney] forKey:@"returnmoney"];
                
            }
            NSLog(@"** End Round ** %@ Win, %@ Lose", rivalPlayer.Username, myPlayer.Username);
            [self.gameRuleProxyCallback doActionCallback:gameInfo];
            break;
        default:
            break;
    }
}
-(void) endRound
{
    NSMutableDictionary * gameInfo = [NSMutableDictionary dictionary];
    NSMutableArray* myBestCard = [NSMutableArray array];
    NSMutableArray* rivalBestCard = [NSMutableArray array];
    [myBestCard addObjectsFromArray:myListCards];
    [myBestCard addObjectsFromArray:turnListCards];
    [CheckCardUtils debugCards:myBestCard tips:@"MyBestCard"];
    [rivalBestCard addObjectsFromArray:rivalListCards];
    [rivalBestCard addObjectsFromArray:turnListCards];
    [CheckCardUtils debugCards:rivalBestCard tips:@"RivalBestCard"];
    BestCardsInfo * myBestCardInfo = [[CheckCardUtils checkBestCard:myBestCard] autorelease];
    BestCardsInfo * rivalBestCardInfo = [[CheckCardUtils checkBestCard:rivalBestCard] autorelease];
    
    [CheckCardUtils debugCards:myBestCardInfo.bestCards tips:[myBestCardInfo debugBestHand]];
    [CheckCardUtils debugCards:rivalBestCardInfo.bestCards tips:[rivalBestCardInfo debugBestHand]];
    ResultCompareCards rCompareCards = [myBestCardInfo compareBestCard:rivalBestCardInfo];

    if(rCompareCards == rCompareWin)
    {
        [gameInfo setObject:@"win" forKey:@"result"];
        long returnMoney;
        if(mMoney >= rMoney)
        {
             [gameInfo setObject:[NSString stringWithFormat:@"%d",tMoney] forKey:@"money"];
             [gameInfo setObject:[NSString stringWithFormat:@"%d",0] forKey:@"returnmoney"];
        }
        else if (mMoney < rMoney) 
        {
            returnMoney = abs(mMoney - rMoney);
            [gameInfo setObject:[NSString stringWithFormat:@"%d",tMoney - returnMoney] forKey:@"money"];
            [gameInfo setObject:[NSString stringWithFormat:@"%d",returnMoney] forKey:@"returnmoney"];
            
        }
        [gameInfo setObject:myBestCardInfo.bestCards forKey:@"bestCard"];
        NSLog(@"==================  End Round ** %@ Win, %@ Lose", myPlayer.Username, rivalPlayer.Username);
    } 
    else if (rCompareCards == rCompareLose)
    {
        [gameInfo setObject:@"lose" forKey:@"result"];
        long returnMoney;
        if(mMoney <= rMoney)
        {
            [gameInfo setObject:[NSString stringWithFormat:@"%d",tMoney] forKey:@"money"];
            [gameInfo setObject:[NSString stringWithFormat:@"%d",0] forKey:@"returnmoney"];
        }
        else if (mMoney > rMoney) 
        {
            returnMoney = abs(mMoney - rMoney);
            [gameInfo setObject:[NSString stringWithFormat:@"%d",tMoney - returnMoney] forKey:@"money"];
            [gameInfo setObject:[NSString stringWithFormat:@"%d",returnMoney] forKey:@"returnmoney"];
            
        }

        [gameInfo setObject:rivalBestCardInfo.bestCards forKey:@"bestCard"];
        NSLog(@"================== End Round ** %@ Win, %@ Lose", rivalPlayer.Username, myPlayer.Username);
    }
    else 
    {
        [gameInfo setObject:@"equal" forKey:@"result"];
        [gameInfo setObject:[NSString stringWithFormat:@"%d",mMoney] forKey:@"mymoney"];
        [gameInfo setObject:[NSString stringWithFormat:@"%d",rMoney] forKey:@"rivalmoney"];
        
        [gameInfo setObject:myBestCardInfo.bestCards forKey:@"myBestCard"];
        [gameInfo setObject:rivalBestCardInfo.bestCards forKey:@"rivalBestCard"];
        
        NSLog(@"================== End Round ** %@ Equal %@", myPlayer.Username, rivalPlayer.Username);
    }

    [self.gameRuleProxyCallback endRoundCallback:gameInfo];
}
-(void) endGame
{
    // TODO: Save Infomation
    NSMutableDictionary * gameInfo = [NSMutableDictionary dictionary];
    [self.gameRuleProxyCallback endGameCallback:gameInfo];
}
-(void) exitGame
{
    // TODO: Calculate End Round and End Game
    NSMutableDictionary * gameInfo = [NSMutableDictionary dictionary];
    [self.gameRuleProxyCallback exitGameCallback:gameInfo];
}
// get random card
-(NSArray*) randRankCard:(int) numCard
{
    NSMutableArray * array = [NSMutableArray array];
    for (int i=0; i < numCard; i++) {
        [array addObject:[self randCard]];
    }
    
    return array;
}
-(Card*) randCard
{
    int nCard = abs(arc4random()) % [cardArr count];
    Card * card = (Card*) [cardArr objectAtIndex:nCard];
    [cardArr removeObject:card];
    return card;
}

-(void) dealloc
{
    [super dealloc];
    [self.gameRuleProxyCallback release];
    self.gameRuleProxyCallback = nil;
    
}
@end
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
